{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "provenance": []
    },
    "kernelspec": {
      "name": "python3",
      "display_name": "Python 3"
    },
    "accelerator": "GPU"
  },
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "LjmhJ4ad9kBL"
      },
      "source": [
        "# Build an Embeddings index with Hugging Face Datasets\n",
        "\n",
        "This notebook shows how txtai can index and search with Hugging Face's [Datasets](https://github.com/huggingface/datasets) library. Datasets opens access to a large and growing list of publicly available datasets. Datasets has functionality to select, transform and filter data stored in each dataset.\n",
        "\n",
        "In this example, txtai will be used to index and query a dataset.\n",
        "\n",
        "**Make sure to select a GPU runtime when running this notebook**"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "8tLWvo9v-Q0u"
      },
      "source": [
        "# Install dependencies\n",
        "\n",
        "Install `txtai` and all dependencies. Also install `datasets`."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "Fa5BCjMFqVKE"
      },
      "source": [
        "%%capture\n",
        "!pip install git+https://github.com/neuml/txtai\n",
        "!pip install datasets"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "hOdEv8MH-e5h"
      },
      "source": [
        "# Load dataset and build a txtai index\n",
        "\n",
        "In this example, we'll load the `ag_news` dataset, which is a collection of news article headlines. This only takes a single line of code!\n",
        "\n",
        "Next, txtai will index the first 10,000 rows of the dataset. A sentence similarity model is used to compute sentence embeddings. sentence-transformers has a number of [pre-trained models](https://huggingface.co/models?pipeline_tag=sentence-similarity) that can be swapped in.\n",
        "\n",
        "In addition to the embeddings index, we'll also create a Similarity instance to re-rank search hits for relevancy. "
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "3hYRk9JnsM0J"
      },
      "source": [
        "%%capture\n",
        "from datasets import load_dataset\n",
        "\n",
        "from txtai.embeddings import Embeddings\n",
        "from txtai.pipeline import Similarity\n",
        "\n",
        "def stream(dataset, field, limit):\n",
        "  index = 0\n",
        "  for row in dataset:\n",
        "    yield (index, row[field], None)\n",
        "    index += 1\n",
        "\n",
        "    if index >= limit:\n",
        "      break\n",
        "\n",
        "def search(query):\n",
        "  return [(result[\"score\"], result[\"text\"]) for result in embeddings.search(query, limit=50)]\n",
        "\n",
        "def ranksearch(query):\n",
        "  results = [text for _, text in search(query)]\n",
        "  return [(score, results[x]) for x, score in similarity(query, results)]\n",
        "\n",
        "# Load HF dataset\n",
        "dataset = load_dataset(\"ag_news\", split=\"train\")\n",
        "\n",
        "# Create embeddings model, backed by sentence-transformers & transformers, enable content storage\n",
        "embeddings = Embeddings({\"path\": \"sentence-transformers/paraphrase-MiniLM-L3-v2\", \"content\": True})\n",
        "embeddings.index(stream(dataset, \"text\", 10000))\n",
        "\n",
        "# Create similarity instance for re-ranking\n",
        "similarity = Similarity(\"valhalla/distilbart-mnli-12-3\")"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "LBhHcX6eFmGI"
      },
      "source": [
        "# Search the dataset\n",
        "\n",
        "Now that an index is ready, let's search the data! The following section runs a series of queries and show the results. Like basic search engines, txtai finds token matches. But the real power of txtai is finding semantically similar results.\n",
        "\n",
        "sentence-transformers has a great overview on [information retrieval](https://www.sbert.net/examples/applications/information-retrieval/README.html) that is well worth a read. "
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "YVmbiY92vxEO",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 1000
        },
        "outputId": "85f5e0ad-14ba-4642-aed6-13c14a710d68"
      },
      "source": [
        "from IPython.core.display import display, HTML\n",
        "\n",
        "def table(query, rows):\n",
        "    html = \"\"\"\n",
        "    <style type='text/css'>\n",
        "    @import url('https://fonts.googleapis.com/css?family=Oswald&display=swap');\n",
        "    table {\n",
        "      border-collapse: collapse;\n",
        "      width: 900px;\n",
        "    }\n",
        "    th, td {\n",
        "        border: 1px solid #9e9e9e;\n",
        "        padding: 10px;\n",
        "        font: 15px Oswald;\n",
        "    }\n",
        "    </style>\n",
        "    \"\"\"\n",
        "\n",
        "    html += \"<h3>%s</h3><table><thead><tr><th>Score</th><th>Text</th></tr></thead>\" % (query)\n",
        "    for score, text in rows:\n",
        "        html += \"<tr><td>%.4f</td><td>%s</td></tr>\" % (score, text)\n",
        "    html += \"</table>\"\n",
        "\n",
        "    display(HTML(html))\n",
        "\n",
        "for query in [\"Positive Apple reports\", \"Negative Apple reports\", \"Best planets to explore for life\", \"LA Dodgers good news\", \"LA Dodgers bad news\"]:\n",
        "  table(query, ranksearch(query)[:2])\n"
      ],
      "execution_count": null,
      "outputs": [
        {
          "output_type": "display_data",
          "data": {
            "text/html": [
              "\n",
              "    <style type='text/css'>\n",
              "    @import url('https://fonts.googleapis.com/css?family=Oswald&display=swap');\n",
              "    table {\n",
              "      border-collapse: collapse;\n",
              "      width: 900px;\n",
              "    }\n",
              "    th, td {\n",
              "        border: 1px solid #9e9e9e;\n",
              "        padding: 10px;\n",
              "        font: 15px Oswald;\n",
              "    }\n",
              "    </style>\n",
              "    <h3>Positive Apple reports</h3><table><thead><tr><th>Score</th><th>Text</th></tr></thead><tr><td>0.9941</td><td>Apple's iPod a Huge Hit in Japan The iPod is proving a colossal hit on the Japanese electronics and entertainment giant's home ground. The tiny white machine is catching on as a fashion statement and turning into a cultural icon here, much the same way it won a fanatical following in the United States.</td></tr><tr><td>0.9886</td><td>Apple tops US consumer satisfaction Recent data published by the American Customer Satisfaction Index (ACSI) shows Apple leading the consumer computer industry with the the highest customer satisfaction.</td></tr></table>"
            ],
            "text/plain": [
              "<IPython.core.display.HTML object>"
            ]
          },
          "metadata": {}
        },
        {
          "output_type": "display_data",
          "data": {
            "text/html": [
              "\n",
              "    <style type='text/css'>\n",
              "    @import url('https://fonts.googleapis.com/css?family=Oswald&display=swap');\n",
              "    table {\n",
              "      border-collapse: collapse;\n",
              "      width: 900px;\n",
              "    }\n",
              "    th, td {\n",
              "        border: 1px solid #9e9e9e;\n",
              "        padding: 10px;\n",
              "        font: 15px Oswald;\n",
              "    }\n",
              "    </style>\n",
              "    <h3>Negative Apple reports</h3><table><thead><tr><th>Score</th><th>Text</th></tr></thead><tr><td>0.9847</td><td>Apple Recalls 28,000 Faulty Batteries Sold with 15-inch PowerBook Apple has had to recall up to 28,000 notebook batteries that were sold for use with their 15-inch PowerBook. Apple reports that faulty batteries sold between January 2004 and August 2004 can overheat and pose a fire hazard.</td></tr><tr><td>0.9795</td><td>Apple Announces Voluntary Recall of Powerbook Batteries Apple, in cooperation with the US Consumer Product Safety Commission (CPSC), announced Thursday a voluntary recall of 15 quot; Aluminum PowerBook batteries. The batteries being recalled could potentially overheat, though no injuries relating ...</td></tr></table>"
            ],
            "text/plain": [
              "<IPython.core.display.HTML object>"
            ]
          },
          "metadata": {}
        },
        {
          "output_type": "display_data",
          "data": {
            "text/html": [
              "\n",
              "    <style type='text/css'>\n",
              "    @import url('https://fonts.googleapis.com/css?family=Oswald&display=swap');\n",
              "    table {\n",
              "      border-collapse: collapse;\n",
              "      width: 900px;\n",
              "    }\n",
              "    th, td {\n",
              "        border: 1px solid #9e9e9e;\n",
              "        padding: 10px;\n",
              "        font: 15px Oswald;\n",
              "    }\n",
              "    </style>\n",
              "    <h3>Best planets to explore for life</h3><table><thead><tr><th>Score</th><th>Text</th></tr></thead><tr><td>0.9110</td><td>Tiny 'David' Telescope Finds 'Goliath' Planet A newfound planet detected by a small, 4-inch-diameter telescope demonstrates that we are at the cusp of a new age of planet discovery. Soon, new worlds may be located at an accelerating pace, bringing the detection of the first Earth-sized world one step closer.</td></tr><tr><td>0.8838</td><td>Venus: Inhabited World? by Harry Bortman    In part 1 of this interview with Astrobiology Magazine editor Henry Bortman, planetary scientist David Grinspoon explained how Venus evolved from a wet planet similar to Earth to the scorching hot, dried-out furnace of today. In part 2, Grinspoon discusses the possibility of life on Venus...</td></tr></table>"
            ],
            "text/plain": [
              "<IPython.core.display.HTML object>"
            ]
          },
          "metadata": {}
        },
        {
          "output_type": "display_data",
          "data": {
            "text/html": [
              "\n",
              "    <style type='text/css'>\n",
              "    @import url('https://fonts.googleapis.com/css?family=Oswald&display=swap');\n",
              "    table {\n",
              "      border-collapse: collapse;\n",
              "      width: 900px;\n",
              "    }\n",
              "    th, td {\n",
              "        border: 1px solid #9e9e9e;\n",
              "        padding: 10px;\n",
              "        font: 15px Oswald;\n",
              "    }\n",
              "    </style>\n",
              "    <h3>LA Dodgers good news</h3><table><thead><tr><th>Score</th><th>Text</th></tr></thead><tr><td>0.9961</td><td>Dodgers 7, Braves 4 Los Angeles, Ca. -- Shawn Green belted a grand slam and a solo homer as Los Angeles beat Mike Hampton and the Atlanta Braves 7-to-4 Saturday afternoon.</td></tr><tr><td>0.9928</td><td>MLB: Los Angeles 7, Atlanta 4 Shawn Green hit two home runs Saturday, including a grand slam, to lead the Los Angeles Dodgers to a 7-4 victory over the Atlanta Braves.</td></tr></table>"
            ],
            "text/plain": [
              "<IPython.core.display.HTML object>"
            ]
          },
          "metadata": {}
        },
        {
          "output_type": "display_data",
          "data": {
            "text/html": [
              "\n",
              "    <style type='text/css'>\n",
              "    @import url('https://fonts.googleapis.com/css?family=Oswald&display=swap');\n",
              "    table {\n",
              "      border-collapse: collapse;\n",
              "      width: 900px;\n",
              "    }\n",
              "    th, td {\n",
              "        border: 1px solid #9e9e9e;\n",
              "        padding: 10px;\n",
              "        font: 15px Oswald;\n",
              "    }\n",
              "    </style>\n",
              "    <h3>LA Dodgers bad news</h3><table><thead><tr><th>Score</th><th>Text</th></tr></thead><tr><td>0.9880</td><td>Expos Keep Dodgers at Bay With 8-7 Win (AP) AP - Giovanni Carrara walked Juan Rivera with the bases loaded and two outs in the ninth inning Monday night, spoiling Los Angeles' six-run comeback and handing the Montreal Expos an 8-7 victory over the Dodgers.</td></tr><tr><td>0.9671</td><td>Gagne blows his 2d save Pinch-hitter Lenny Harris delivered a three-run double off Eric Gagne with two outs in the ninth, rallying the Florida Marlins past the Dodgers, 6-4, last night in Los Angeles.</td></tr></table>"
            ],
            "text/plain": [
              "<IPython.core.display.HTML object>"
            ]
          },
          "metadata": {}
        }
      ]
    }
  ]
}